package monitor;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.TimerTask;

import environment.Application;
import environment.Environment;
import environment.PhysicalMachine;
import environment.VirtualMachine;

public class MonitorTask extends TimerTask {

	@Override
	public void run() {
		
		/* print info about the environment */ 
		printEnvironmentState();
		
		/* check if there are new or finished applications */
		checkApps();
	}
	
	private void checkApps()
	{
		for(PhysicalMachine pm : Environment.physicalMachines)
		{
			if(!pm.isRunning() || pm.isMaybeTerminated())
				continue;
			
			for(VirtualMachine vm : pm.getVirtualMachines())
			{				
				List<Application> finishedApps = new ArrayList<Application>();
				for(Application app : vm.getApplications())
					if(processApp(app))
						finishedApps.add(app);
				
				// remove apps
				for(Application app : finishedApps)
					vm.removeApplication(app);
			}
		}	
		
		// federations
		for(int i=Environment.federations.size()-1; i>=0; i--)
		{
			Application app = Environment.federations.get(i);
			if(processApp(app))
				Environment.federations.remove(app);
		}
	}
	
	private boolean processApp(Application app)
	{		
		boolean isAppFinished = false;
		
		if(!app.isRunning())
			app.start();
		
		// execution time has been reached
		if(app.getCpuCycles()==0)
		{
			app.stop();
			isAppFinished = true;
		}
		else
		{
			// adapt app and vm load
			Integer minLoad = app.getMaxCPUs() / 2;
			Integer maxLoad = app.getMaxCPUs();
			
			Integer load = new Random().nextInt(maxLoad-minLoad+1)+minLoad;   
			
			app.removeCPUCycle();
			app.setLoadCPUs(load);
		}
		
		return isAppFinished;
	}
	
	private void printEnvironmentState() 
	{
		System.out.println("\nMONITOR:");
		
		for(PhysicalMachine pm : Environment.physicalMachines)
		{	
			System.out.println(pm.toString());
			
			for(VirtualMachine vm : pm.getVirtualMachines())
			{
				System.out.println(" " + vm.toString());
				
				for(Application app : vm.getApplications())
					System.out.println("  " + app.toString());
			}
		}
		
		if(Environment.federations.size() > 0)
		{
			System.out.println("[Federations]");
			for(Application app : Environment.federations)
				System.out.println(" " + app.toString());
		}
		
		System.out.println("\n-----------------------------");
			
	}	

}
